package com.t3.animation
{
	import com.t3.display.Thumbnail;
	import com.t3.events.AnimationEvent;
	
	import flash.display.Shape;
	import flash.display.Sprite;
	import flash.events.TimerEvent;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.utils.Timer;

	public class PointAnimation extends Sprite
	{
		private var _points:Array;
		private var _timer:Timer;
		private var _duration:uint;
		private var _sketch:Shape;
		private var _thumb:Thumbnail;
		private var _bounds:Rectangle;
		private var _framerate:uint;
		private var _ppf:uint;
		
		public function PointAnimation( bounds:Rectangle, frameRate:uint = 24, points:Array = null, duration:uint = 10000 )
		{
			this._framerate = frameRate;
			this._points = points;
			this._duration = duration;
			this._bounds = bounds;
			
			_sketch = new Shape();
			_thumb = new Thumbnail( bounds, _sketch, 1, false, true );
			
			addChild( _thumb );
			addChild( _sketch );
			
			_timer = new Timer( 50, 0 );
			_timer.addEventListener( TimerEvent.TIMER, nextPoints );
			_timer.addEventListener( TimerEvent.TIMER_COMPLETE, animationComplete );
		}
		
		public function set animatedObjects( objects:Array ):void
		{
			_points = new Array();
			
			for each( var object:AnimatedObject in objects )
			{
				addAnimatedObject( object );
			}
		}
		
		public function addAnimatedObject( object:AnimatedObject ):void
		{
			_points.push( object.color );

			for each( var point:Point in object.points )
			{
				_points.push( point );
			}
		}
		
		public function set points( points:Array ):void
		{
			this._points = points;
		}
		
		public function get points():Array
		{
			return _points;
		}
		
		public function set duration( ms:uint ):void
		{
			this._duration = ms;
		}
		
		public function get duration():uint
		{
			return _duration;
		}
		
		public function get running():Boolean
		{
			return _timer.running;
		}
		
		public function start():void
		{			
			if( _timer.running )
			{
				this.reset();
			}
			else
			{
				var frameDuration:uint = 1000 / _framerate;
				var interval:uint = duration / points.length;
				
				_ppf = frameDuration > interval ? Math.round( frameDuration/interval ) : 1;
				
				this._timer.delay = interval < frameDuration ? frameDuration : interval;
				this._timer.repeatCount = Math.ceil( points.length / _ppf );
				this._timer.start();
			}
		}
		
		public function reset():void
		{
			this._timer.stop();
			this._timer.reset();
			this._sketch.graphics.clear();
			this._thumb.clear();
		}
		
		private function nextPoints( event:TimerEvent ):void
		{
			var index:uint = ( _timer.currentCount - 1 ) * _ppf;
			
			for( var i:uint = 0; i < _ppf; i++ )
			{
				nextPoint( index+i );
			}
		}

		private function nextPoint( index:uint ):void
		{	
			if( points[ index ] != null )
			{
				var point:Point;
				
				if( points[ index ] is Number )
				{
					_thumb.updateThumb();
					point = points[ index + 1 ];
					this._sketch.graphics.clear();
					this._sketch.graphics.lineStyle( 20, points[ index ] );
					this._sketch.graphics.moveTo( point.x - _bounds.x, point.y - _bounds.y );
				}
				else if( points[ index ] is Point )
				{
					point = points[ index ];
					this._sketch.graphics.lineTo( point.x - _bounds.x, point.y - _bounds.y );
					this._sketch.graphics.moveTo( point.x - _bounds.x, point.y - _bounds.y );
				}
			} 
		}
		
		private function animationComplete( event:TimerEvent ):void
		{
			this.dispatchEvent( new AnimationEvent( AnimationEvent.ANIMATION_FINISH ) );
			this.reset();
		}
	}
}